import { NIcon } from "naive-ui";
import { Component, h, reactive } from "vue";
import { v4 as uuidv4 } from "uuid";
import { LogoReddit, MaleFemaleOutline, MaleOutline } from "@vicons/ionicons5";
import { upload } from "@/api";
import { ElMessage } from "element-plus";
import { ChatType, IMessage, MessageType } from "@/types/chat";
import { ISession } from "@/types/session";
import { useCache } from "@/store/modules/cache";
import { useUser } from "@/store/modules/user";
import { useChat } from "@/store/modules/chat.ts";
import axios from "axios";
import { IWeatherData, IWeatherSevenDayForecast, IWeatherDayHourForecast } from "@/types/system";
import { useSystem } from "@/store/modules/system";

export const Logo = new URL("@/assets/images/logo.jpg", import.meta.url).href;

export const LoginRules = reactive({
  name: [{ required: true, message: "请输入用户名", trigger: "blur" }],
  password: [
    {
      required: true,
      message: "请输入密码",
      trigger: "change",
    },
  ],
  captchaVal: [
    {
      required: true,
      message: "请输入密码",
      trigger: "change",
    },
  ],
});
export const RegisterRules = reactive({
  name: [{ required: true, message: "请输入用户名", trigger: "blur" }],
  password: [
    {
      required: true,
      message: "请输入密码",
      trigger: "change",
    },
  ],
  repeat_password: [
    {
      required: true,
      message: "请输入重复密码",
      trigger: "change",
    },
  ],
  captchaVal: [
    {
      required: true,
      message: "请输入密码",
      trigger: "change",
    },
  ],
});

export const SexOptions = [
  {
    value: 0,
    label: "未知",
  },
  {
    value: 1,
    label: "男",
  },
  {
    value: 2,
    label: "女",
  },
];

export const SelectFileListOption = [
  {
    id: 1,
    value: 1,
    label: "按新时间排序",
  },
  {
    id: 2,
    value: 2,
    label: "按旧时间排序",
  },
  {
    id: 3,
    value: 3,
    label: "按文件从大到小",
  },
  {
    id: 4,
    value: 4,
    label: "按文件从小到大",
  },
];

export function RenderIcon(icon: Component, color = "text-fontPrimary") {
  return () => {
    return h(NIcon, null, {
      default: () => h(icon, { class: color }),
    });
  };
}

export function Gender(gender: number) {
  switch (gender) {
    case 1:
      return RenderIcon(MaleOutline, "text-blue-500");
    case 2:
      return RenderIcon(MaleFemaleOutline, "text-pink-500");
    default:
      return RenderIcon(LogoReddit, "text-blue-500");
  }
}

export function Debounce(callback: Function, time: number = 300) {
  let timer: NodeJS.Timeout | null = null;
  return (...args: any[]) => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => callback(...args), time);
  };
}

export function Throttle(func: (...args: any[]) => void, wait: number = 300) {
  let timeout: NodeJS.Timeout | null = null;
  return (...args: any[]) => {
    if (!timeout) {
      timeout = setTimeout(() => {
        timeout = null;
        func(...args);
      }, wait);
    }
  };
}

export function GenerateUUid(): number {
  let uuid = uuidv4();
  let hash = 0;
  for (let i = 0; i < uuid.length; i++) {
    hash = (hash << 5) - hash + uuid.charCodeAt(i);
    hash |= 0;
  }
  return Math.abs(hash);
}

export function GenerateStringUUid(): string {
  let uuid = uuidv4();
  return uuid;
}

type CallBackFunc = (result: string | null) => void;

// 上传文件
export async function UploadFile(file: File, callBack?: CallBackFunc) {
  if (!checkFileType(file)) return;
  let result = null;
  try {
    let formData = new FormData();
    formData.append("file", file);
    result = await upload(formData, {});
    if (!result || result.status != 200) throw Error("服务器响应失败");
    return result.data;
  } catch (error) {
    ElMessage.error("上传失败: " + String(error));
  } finally {
    if (callBack) callBack(result ? result.data : null);
  }
}

// 检查文件类型
function checkFileType(file: File): boolean {
  switch (true) {
    case file.type.startsWith("image/"):
      return checkImageSize(file);
    default:
      return true;
  }
}

// 检查文件大小
function checkImageSize(file: File): boolean {
  const maxSizeInMB = 15;
  const maxSizeInBytes = maxSizeInMB * 1024 * 1024;
  if (file.size > maxSizeInBytes) {
    ElMessage.error(`图片大小不能超过 ${maxSizeInMB}MB`);
    return false;
  }
  return true;
}

// 构建新的session
export function BuildNewSession(message: IMessage, isLocal: boolean): ISession {
  const { name, avatar, sendId } = getSessionSendInfo(message, isLocal);
  return {
    ownerId: isLocal ? sendId : message.toId,
    toId: isLocal ? message.toId : sendId,
    sessionId: message.sessionId,
    chatType: message.chatType,
    sessionType: message.messageType,
    content: BuildSessionContent(message),
    isPinned: 0,
    isDel: 0,
    unread: isLocal ? 0 : 1,
    name,
    avatar,
    updatedAt: new Date().toString(),
  };
}

export function BuildSessionContent(message: IMessage): string {
  switch (message.messageType) {
    case MessageType.withdraw:
      return message.sendId === useUser().userId ? "你撤回了一条消息" : "对方撤回了一条消息";
    default:
      return message.content;
  }
}

function getSessionSendInfo(message: IMessage, isLocal: boolean) {
  const cache = useCache();
  if (message.chatType === ChatType.group) {
    let info = cache.GetGroupInfo(message.sendId);
    const { name, avatar } = info || { name: "", avatar: "" };
    const sendId = message.groupId!;
    return { name, avatar, sendId };
  }
  let info = cache.GetFriendInfo(isLocal ? message.toId : message.sendId);
  const { name, avatar } = info || { name: "", avatar: "" };
  return { name, avatar, sendId: message.sendId };
}

export function RemoveAllCache() {
  useUser().ResetUser();
  useCache().ResetCache();
  useChat().ResetChat();
}

// 获取今日天气
export async function GetTodayWeather(): Promise<IWeatherData | null> {
  const system = useSystem();
  const key = import.meta.env.VITE_WheatherApiKey;
  if (!system.UserLocationData) await system.GetUserLocation();
  const { lon, lat } = system.UserLocationData!;
  try {
    const res = await axios.get(`https://devapi.qweather.com/v7/weather/now?location=${lon},${lat}&key=${key}`);
    if (res.status === 200) {
      return res.data.now as IWeatherData;
    }
  } catch (e) {
    console.warn("获取天气失败", e);
  }

  return null;
}

// 获取今天小时预报
export async function GetDayHourForecast(): Promise<IWeatherDayHourForecast[] | null> {
  const system = useSystem();
  const key = import.meta.env.VITE_WheatherApiKey;
  if (!system.UserLocationData) await system.GetUserLocation();
  const { lon, lat } = system.UserLocationData!;
  try {
    const res = await axios.get(`https://devapi.qweather.com/v7/weather/24h?location=${lon},${lat}&key=${key}`);
    if (res.status === 200) {
      return res.data.hourly as IWeatherDayHourForecast[];
    }
  } catch (e) {
    console.warn("获取天气失败", e);
  }
  return null;
}

// 获取七天天气预报
export async function GetSevenDayForecast(): Promise<IWeatherSevenDayForecast[] | null> {
  const system = useSystem();
  const key = import.meta.env.VITE_WheatherApiKey;
  if (!system.UserLocationData) await system.GetUserLocation();
  const { lon, lat } = system.UserLocationData!;
  try {
    const res = await axios.get(`https://devapi.qweather.com/v7/weather/7d?location=${lon},${lat}&key=${key}`);
    if (res.status === 200) {
      return res.data.daily as IWeatherSevenDayForecast[];
    }
  } catch (e) {
    console.warn("获取天气失败", e);
  }
  return null;
}
